#pragma once
#ifndef _MATERIAL_
#define _MATERIAL_

//================================================================================================================================
//================================================================================================================================
#include <cmath>
#include <limits>
#define NaN std::numeric_limits<double>::quiet_NaN()

//================================================================================================================================
//================================================================================================================================
class Material
{
public:
    //****************************************************************************************************************************
    //****************************************************************************************************************************
    // Физические свойства вещества
    enum Property
    {
        Density             = 0,    // Плотность, кг/м^3.
        Viscosity           = 1,    // Кинематическая вязкость, м^2/с.
        HeatCapacity        = 2,    // Удельная теплоемкость, Дж/(кг*К).
        Expansiveness       = 3,    // Коэффициент теплового расширения, К^-1.
        HeatConductivity    = 4,    // Теплопроводность, Вт/(м*К).
        CrystallizationHeat = 5,    // Удельная теплота кристаллизации, Дж/кг.
        MolarMass           = 6,    // Молярная масса, г/моль.
        Diffusivity         = 7,    // Коэффициент диффузии, м^2/с.
        SegregationFactor   = 8     // Коэффициент сегрегации.
    };

    // Агрегатное состояние вещества
    enum AggregateState
    {
        Solid,              // Твердое.
        Liquid,             // Жидкое.
        Gaseous,            // Газообразное.
        Admixture,          // Примесь.
        Undefined           // Не определено.
    };

    //****************************************************************************************************************************
    //****************************************************************************************************************************
    explicit Material(AggregateState aggregate_state) : m_State(aggregate_state)
    {
        for(int i = 0; i < m_NumOfKnownProperties; ++i)
            m_Properties[i] = NaN;
    }

    //****************************************************************************************************************************
    //****************************************************************************************************************************
    AggregateState state() const {return m_State;}

    double property(Property property_name) const
    {
#if defined(Q_CC_MSVC)
        Q_ASSERT_X(!_isnan(m_Properties[property_name]), "Material::getProperty", "Unknown property value");
#elif defined(Q_CC_GNU)
        Q_ASSERT_X(!std::isnan(m_Properties[property_name]), "Material::getProperty", "Unknown property value");
#endif
        return m_Properties[property_name];
    }

    void setProperty(Property property_name, double property_value) {m_Properties[property_name] = property_value;}

private:
    //****************************************************************************************************************************
    //****************************************************************************************************************************
    static const int m_NumOfKnownProperties = 9;    // Число физических свойств, известных классу.
    double m_Properties[m_NumOfKnownProperties];    // Физические свойства вещества.
    AggregateState m_State;                         // Агрегатное состояние вещества.
};

#endif // _MATERIAL_
